<?php
    /**
     * PHPExcel
     * Copyright (c) 2006 - 2015 PHPExcel
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
     * version 2.1 of the License, or (at your option) any later version.
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
     * You should have received a copy of the GNU Lesser General Public
     * License along with this library; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     * @category   PHPExcel
     * @package    PHPExcel_Shared
     * @copyright  Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
     * @license    http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt    LGPL
     * @version    ##VERSION##, ##DATE##
     */

    /**
     * PHPExcel_Shared_Drawing
     * @category   PHPExcel
     * @package    PHPExcel_Shared
     * @copyright  Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
     */
    class PHPExcel_Shared_Drawing {
        /**
         * Convert pixels to EMU
         * @param     int $pValue Value in pixels
         * @return     int            Value in EMU
         */
        public static function pixelsToEMU($pValue = 0) {
            return round($pValue * 9525);
        }

        /**
         * Convert EMU to pixels
         * @param     int $pValue Value in EMU
         * @return     int            Value in pixels
         */
        public static function EMUToPixels($pValue = 0) {
            if ($pValue != 0) {
                return round($pValue / 9525);
            } else {
                return 0;
            }
        }

        /**
         * Convert pixels to column width. Exact algorithm not known.
         * By inspection of a real Excel file using Calibri 11, one finds 1000px ~ 142.85546875
         * This gives a conversion factor of 7. Also, we assume that pixels and font size are proportional.
         * @param     int                 $pValue       Value in pixels
         * @param     PHPExcel_Style_Font $pDefaultFont Default font of the workbook
         * @return     int            Value in cell dimension
         */
        public static function pixelsToCellDimension($pValue = 0, PHPExcel_Style_Font $pDefaultFont) {
            // Font name and size
            $name = $pDefaultFont->getName();
            $size = $pDefaultFont->getSize();
            if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) {
                // Exact width can be determined
                $colWidth = $pValue * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width'] / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px'];
            } else {
                // We don't have data for this particular font and size, use approximation by
                // extrapolating from Calibri 11
                $colWidth = $pValue * 11 * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] / $size;
            }
            return $colWidth;
        }

        /**
         * Convert column width from (intrinsic) Excel units to pixels
         * @param     float               $pValue       Value in cell dimension
         * @param     PHPExcel_Style_Font $pDefaultFont Default font of the workbook
         * @return     int        Value in pixels
         */
        public static function cellDimensionToPixels($pValue = 0, PHPExcel_Style_Font $pDefaultFont) {
            // Font name and size
            $name = $pDefaultFont->getName();
            $size = $pDefaultFont->getSize();
            if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) {
                // Exact width can be determined
                $colWidth = $pValue * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px'] / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width'];
            } else {
                // We don't have data for this particular font and size, use approximation by
                // extrapolating from Calibri 11
                $colWidth = $pValue * $size * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] / 11;
            }
            // Round pixels to closest integer
            $colWidth = (int)round($colWidth);
            return $colWidth;
        }

        /**
         * Convert pixels to points
         * @param     int $pValue Value in pixels
         * @return     int            Value in points
         */
        public static function pixelsToPoints($pValue = 0) {
            return $pValue * 0.67777777;
        }

        /**
         * Convert points to pixels
         * @param     int $pValue Value in points
         * @return     int            Value in pixels
         */
        public static function pointsToPixels($pValue = 0) {
            if ($pValue != 0) {
                return (int)ceil($pValue * 1.333333333);
            } else {
                return 0;
            }
        }

        /**
         * Convert degrees to angle
         * @param     int $pValue Degrees
         * @return     int            Angle
         */
        public static function degreesToAngle($pValue = 0) {
            return (int)round($pValue * 60000);
        }

        /**
         * Convert angle to degrees
         * @param     int $pValue Angle
         * @return     int            Degrees
         */
        public static function angleToDegrees($pValue = 0) {
            if ($pValue != 0) {
                return round($pValue / 60000);
            } else {
                return 0;
            }
        }

        /**
         * Create a new image from file. By alexander at alexauto dot nl
         * @link http://www.php.net/manual/en/function.imagecreatefromwbmp.php#86214
         * @param string $filename Path to Windows DIB (BMP) image
         * @return resource
         */
        public static function imagecreatefrombmp($p_sFile) {
            //    Load the image into a string
            $file = fopen($p_sFile, "rb");
            $read = fread($file, 10);
            while (!feof($file) && ($read <> "")) {
                $read .= fread($file, 1024);
            }
            $temp   = unpack("H*", $read);
            $hex    = $temp[1];
            $header = substr($hex, 0, 108);
            //    Process the header
            //    Structure: http://www.fastgraph.com/help/bmp_header_format.html
            if (substr($header, 0, 4) == "424d") {
                //    Cut it in parts of 2 bytes
                $header_parts = str_split($header, 2);
                //    Get the width        4 bytes
                $width = hexdec($header_parts[19] . $header_parts[18]);
                //    Get the height        4 bytes
                $height = hexdec($header_parts[23] . $header_parts[22]);
                //    Unset the header params
                unset($header_parts);
            }
            //    Define starting X and Y
            $x = 0;
            $y = 1;
            //    Create newimage
            $image = imagecreatetruecolor($width, $height);
            //    Grab the body from the image
            $body = substr($hex, 108);
            //    Calculate if padding at the end-line is needed
            //    Divided by two to keep overview.
            //    1 byte = 2 HEX-chars
            $body_size   = (strlen($body) / 2);
            $header_size = ($width * $height);
            //    Use end-line padding? Only when needed
            $usePadding = ($body_size > ($header_size * 3) + 4);
            //    Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption
            //    Calculate the next DWORD-position in the body
            for ($i = 0; $i < $body_size; $i += 3) {
                //    Calculate line-ending and padding
                if ($x >= $width) {
                    // If padding needed, ignore image-padding
                    // Shift i to the ending of the current 32-bit-block
                    if ($usePadding) {
                        $i += $width % 4;
                    }
                    //    Reset horizontal position
                    $x = 0;
                    //    Raise the height-position (bottom-up)
                    $y++;
                    //    Reached the image-height? Break the for-loop
                    if ($y > $height) {
                        break;
                    }
                }
                // Calculation of the RGB-pixel (defined as BGR in image-data)
                // Define $i_pos as absolute position in the body
                $i_pos = $i * 2;
                $r     = hexdec($body[$i_pos + 4] . $body[$i_pos + 5]);
                $g     = hexdec($body[$i_pos + 2] . $body[$i_pos + 3]);
                $b     = hexdec($body[$i_pos] . $body[$i_pos + 1]);
                // Calculate and draw the pixel
                $color = imagecolorallocate($image, $r, $g, $b);
                imagesetpixel($image, $x, $height - $y, $color);
                // Raise the horizontal position
                $x++;
            }
            // Unset the body / free the memory
            unset($body);
            //    Return image-object
            return $image;
        }
    }
